﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using VitCode.Castle.Entities;

namespace VitCode.Castle.DataAccess
{
    /// <summary>
    /// 通用的自定义上下文对象
    /// </summary>
    public class GenericContext
    {
      
        /// <summary>
        /// Web应用中Context保存的键值
        /// </summary>
        private const string ContextKey = "nhibernate.current_session";

        /// <summary>
        /// 标识当前应用是否为Web应用
        /// </summary>
        private static readonly bool m_IsWeb = CheckWhetherIsWeb();

        /// <summary>
        /// 用于Windows应用的线程级上下文成员容器
        /// </summary>
        [ThreadStatic]
        private static NameBasedDictionary _threadCache;

        /// <summary>
        /// 对于Web应用，如果HttpContext对应内容元素没有初始化，则放置一个空容器
        /// 对于Windows应用，由于threadCache为[ThreadStatic]，无需该过程
        /// </summary>
        public GenericContext()
        {
              
            if (m_IsWeb && (HttpContext.Current.Items[ContextKey] == null))
                HttpContext.Current.Items[ContextKey] = new NameBasedDictionary();
        }

        private static string GetCurrValue(string cookKey,HttpRequest request)
        {
            string reVal = "";
            if(string.IsNullOrEmpty(cookKey))
                return reVal;
            if (request.Cookies != null)
            {
                HttpCookieCollection cc = request.Cookies;
                if (cc != null && (cc[cookKey]) != null)
                    reVal = cc[cookKey].Value;
            }
            if (reVal != null && reVal.Length == 0 && HttpContext.Current != null && HttpContext.Current.Items != null)
            {
                object reObj = HttpContext.Current.Items[cookKey];
                if (reObj == null)
                {
                    if (HttpContext.Current.Session[cookKey] != null)
                        reObj = HttpContext.Current.Session[cookKey];
                }
                if (reObj != null)
                    reVal = reObj.ToString();

            }
            return reVal;
        }

        private static string GetCurrValue(string cookKey)
        {
            string reVal = "";
            reVal = GetCurrValue(cookKey, HttpContext.Current.Request);
            if (reVal != null && reVal.Length == 0 && HttpContext.Current != null && HttpContext.Current.Items != null)
            {
                object reObj = HttpContext.Current.Items[cookKey];
                if (reObj == null)
                {
                    if (HttpContext.Current.Session[cookKey] != null)
                        reObj = HttpContext.Current.Session[cookKey];
                }
                if (reObj != null)
                    reVal = reObj.ToString();

            }
            return reVal;
        }

        public static void SetCurrValueByRequestFromPage(Page page)
        {
            SetCurrValue(AMS_CURR_USER_CODE, GetCurrValue(AMS_CURR_USER_CODE, page.Request));
            SetCurrValue(AMS_CURR_USER_ID, GetCurrValue(AMS_CURR_USER_ID, page.Request));
            SetCurrValue(AMS_CURR_USER_NAME, GetCurrValue(AMS_CURR_USER_NAME, page.Request));


        }

        private static void SetCurrValue(string strKey,string val)
        {
            HttpContext.Current.Items[strKey] = val;
            HttpContext.Current.Session[strKey] = val;
            HttpContext.Current.Request.Cookies.Set(new HttpCookie(strKey, val));
        }

        private const string AMS_CURR_USER_CODE = "AMS_CurrUserCode";
        public static string CurrUserCode
        {
            get
            {
                return GetCurrValue(AMS_CURR_USER_CODE);
            }
            set
            {
                SetCurrValue(AMS_CURR_USER_CODE,value);
            }
        }
        private const string AMS_CURR_USER_ID = "AMS_CurrUserId";
        public static Guid CurrUserId
        {
            get
            {
                string strId = GetCurrValue(AMS_CURR_USER_ID);
                if (strId == null || strId.Length != 36)
                    strId = Guid.Empty.ToString();
                return new Guid(strId);
            }
            set
            {
                SetCurrValue(AMS_CURR_USER_ID, value.ToString());
            }
        }
        private const string AMS_CURR_USER_NAME = "AMS_CurrUserName";
        public static string CurrUserName
        {
            get
            {
                return GetCurrValue(AMS_CURR_USER_NAME);
            }
            set
            {
                SetCurrValue(AMS_CURR_USER_NAME, value);
            }
        }



        /// <summary>
        /// 获取当前的系统用户(是一个数据提取过程)
        /// </summary>
        public static User GetCurrUser()
        {
            CastleAccess acc = new CastleAccess();
            try
            {
                return acc.GetUser(CurrUserId);
            }
            finally
            {
                acc.CloseSession();
            }
        }

        /// <summary>
        /// 根据上下文成员名称，返回对应内容
        /// </summary>
        /// <remarks>
        /// 由于threadCache或HttpContext中的缓冲对象都会在构造过程中创建
        /// 因此，这里没有对cache==null的判断
        /// </remarks>
        /// <param name="name"></param>
        /// <returns></returns>
        public virtual object this[string name]
        {
            get
            {
                if (string.IsNullOrEmpty(name)) return null;
                NameBasedDictionary cache = GetCache();
                if (cache.Count <= 0) return null;
                object result;
                if (cache.TryGetValue(name, out result))
                    return result;
                return null;
            }
            set
            {
                if (string.IsNullOrEmpty(name)) return;
                NameBasedDictionary cache = GetCache();
                object temp;
                if (cache.TryGetValue(name, out temp))
                    cache[name] = value;
                else
                    cache.Add(name, value);
            }
        }

        /// <summary>
        /// 根据应用类型获取相应上下文缓冲对象
        /// </summary>
        /// <returns>缓冲对象</returns>
        private static NameBasedDictionary GetCache()
        {
            NameBasedDictionary cache;
            if (m_IsWeb)
                cache = (NameBasedDictionary)HttpContext.Current.Items[ContextKey];
            else
                cache = _threadCache;

            if (cache == null)
                cache = new NameBasedDictionary();
            if (m_IsWeb)
                HttpContext.Current.Items[ContextKey] = cache;
            else
                _threadCache = cache;
            return cache;
        }

     

        /// <summary>
        /// 判断当前应用是否为Web应用的Helper方法（非官方方法）
        /// </summary>
        /// <returns></returns>
        private static bool CheckWhetherIsWeb()
        {
            bool result = false;
            AppDomain domain = AppDomain.CurrentDomain;
            try
            {
                if (domain.ShadowCopyFiles)
                    result = (HttpContext.Current.GetType() != null);
            }
            catch (Exception ex)
            {
                throw ex.InnerException;
            }
            return result;
        }

        #region Nested type: NameBasedDictionary

        /// <summary>
        /// 由于内部操作上，所有的容器类型均为Dictionary<string, object>
        /// 所以定义一个固定的类型名称
        /// </summary>
        private class NameBasedDictionary : Dictionary<string, object>
        {
        }

        #endregion
    }
}